home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
227_01
/
graf.c
< prev
next >
Wrap
Text File
|
1988-02-07
|
42KB
|
1,502 lines
/*
* g r a f . c
* -----------
* This is the hardware-independant, high-level part of the compatible
* graphics library.
*
* update history
* --------------
* May, 27. 1987 Use extended functionality of the hercules low-level
* driver. This driver now allows to write 8 pixel with
* one function call, what dramatically decraeses execution
* time.
* May, 30. 1987 Same as above for the ega low-level driver.
* Also stack space and execution time needed by paint
* reduced, theirby removing a undocumented function
* (paintfil).
* May, 31. 1987 Function "polyline" added; begin use of graphics error
* system.
* Jul, 25. 1987 Begin implemention on reverse-color functions.
* Aug, 30. 1987 Function fellipsis implemented.
* Implemention of reverse-color funtions cancelled,
* begin implemention of the more powerful write mode
* system (includes reverse colors).
* Nov, 14. 1987 wrtpixel function added.
*
* Written by Rainer Gerhards
* Petronellastr. 6
* D-5112 Baesweiler
* West Germany
* Phone (49) 2401 - 1601
*/
/*
* Define library implemention mode - forbidden for user!
*/
#define LIB_MODE 2 /* I am the Master module! */
#include <stdio.h>
#include <dos.h>
#include <math.h>
#ifdef __TURBOC__
#include <stdlib.h>
#endif
#include "graphics.h"
#define last3bit(x) ((x) & 0x0007)
#define exclst3b(x) ((x) & ~0x0007)
/*
* global data-items (the user program may access these items) ...
* are 'til now (Jun, 20. 1987) defined in "graphics.h"!
*/
/*
* The following static items are used by the global/local coordinate system.
*/
static float x_start = 0.0; /* Beginning x coordinate */
static float x_step = 1.0; /* size of a logical x - unit */
static float y_start = 0.0; /* Beginning y coordinate */
static float y_step = 1.0; /* size of a logical y - unit */
/*
* function prototypes (if allowed)
*/
#ifdef USEPROTT
extern void hline(int, int, int, int);
extern int paintfil(int, int);
extern int selcolor(int, int);
extern void fline(int, int, int, int);
extern void ffillbox(int, int, int, int);
#endif
/*
* Auxiliary function set,
* the following functions are only called internally from other
* functions within this module. This function set duplicates most
* of the main function set functions, with the execpetion that
* the functions containd in the auxiliary perform their operation
* in the non-standard write modes (writemod != WM_NORM).
*
* This improves speed dramatically, but unfortunatly needs a lot
* of memory. If anyone think's that the memory requirements are to
* big, please contact me. I then will implement an much smaller (but
* also much slower) function set. I don't implement it today, because
* I see no reason for it. I hope the CP/M programmers will share this
* opinion.
*/
int selcolor(x, y)
int x, y;
/*
* name selcolor
*
* synopsis color = selcolor(x, y);
* int x, y; pixel coordinate
*
* description This function selects the drawing color acording to the
* current write mode and the requested color.
*
* Note The requested color must be contained in field curcolor!
*/
{
register int retcolor; /* selected color */
retcolor = getpixel(x, y);
switch(writemod)
{
case WM_XOR: retcolor ^= curcolor;
break;
case WM_AND: retcolor &= curcolor;
break;
case WM_OR: retcolor |= curcolor;
break;
case WM_INV: retcolor = ~retcolor;
break;
}
return(retcolor);
}
static void fline(x1, y1, x2, y2)
int x1, y1;
int x2, y2;
/**
* name fline
*
* synopsis line(x1, y1, x2, y2);
* int x1, y1; starting coordinate
* int x2, y2; ending coordinate
*
* description This function draws a line of "color" between the
* starting (x1, y1) and ending (x2, y2) coordinate.
**/
{
register int count; /* loop counter, highest difference */
register int berr;
int ix, ox, iy, oy;
int zwsp; /* to swap x2 and y2 */
if(y1 == y2) /* horizontal line? */
{
if(x1 > x2)
{
zwsp = x1;
x1 = x2;
x2 = zwsp;
}
for( ; x1 <= x2 ; ++x1)
setpixel(x1, y1, selcolor(x1, y1));
}
else if(x1 == x2) /* vertikal line? */
{
if(y1 > y2)
{
zwsp = y1;
y1 = y2;
y2 = zwsp;
}
for( ; y1 <= y2 ; y1++)
setpixel(x1, y1, selcolor(x1, y1));
}
else
{
if((x2 -= x1) > 0) /* x difference */
ix = ox = 1; /* add in loop */
else
{
ix = ox = -1; /* subtract in loop */
x2 = -x2; /* use absolute difference! */
}
if((y2 -= y1) > 0) /* y difference */
iy = oy = 1; /* add in loop */
else
{
iy = oy = -1; /* subtract in loop */
y2 = -y2; /* use absolute difference! */
}
if(x2 >= y2) /* select inner/outer loop to add/subtract */
{
zwsp = x2; /* swap x2, y2 */
x2 = y2;
y2 = zwsp;
ix = /* modify x-coordinate in outer */
oy = 0; /* and y-coordinate in inner loop */
}
else
iy = /* modify y-coordinate in outer */
ox = 0; /* and x-coordinate in inner loop */
berr = (x2 << 1) - y2;
count = y2 + 1;
do /* main loop, draws line */
{
setpixel(x1, y1, selcolor(x1, y1));
if(berr > 0)
{
berr += (x2 - y2) << 1;
x1 += ix;
y1 += iy;
}
else
berr += x2 << 1;
x1 += ox;
y1 += oy;
}
while(--count > 0); /* warning: do ... while! */
}
}
static void ffillbox(x1, y1, x2, y2)
register int x1;
int y1;
int x2, y2;
/**
* name fillbox
*
* synopsis fillbox(x1, y1, x2, y2, color);
* int x1, y1; upper left corner
* int x2, y2; lower right corner
* int color; fill color
*
* description This function fills a given box with the specified color.
* The box is specified through the upper left (x1, y1) and
* the lower right (x2, y2) corner.
* This function is the counterpart to box, which draws the
* border.
**/
{
int zwsp; /* to swap coordinates */
register int yt; /* temporary y, inner loop */
if(x1 > x2)
{
zwsp = x1;
x1 = x2;
x2 = zwsp;
}
if(y1 > y2)
{
zwsp = y1;
y1 = y2;
y2 = zwsp;
}
for( ; x1 <= x2 ; ++x1) /* x loop */
for(yt = y1 ; yt <= y2 ; ++yt) /* y loop */
setpixel(x1, yt, selcolor(x1, yt));
}
static void fcircle(x, y, radius, aspect)
register int x, y;
int radius;
double aspect;
/**
* name circle
*
* synopsis circle(x, y, radius, color, aspect)
* int x, y; center coordinate
* int radius; circle radius
* double aspect; aspect ratio
*
* description This function draws a circle.
**/
{
long asp; /* use internal long - its faster */
unsigned int invrad; /* inverse radius - grows form 0 to radius/2 */
int decision; /* controls decrement of radius */
int tmp; /* temporary to modify desicion */
unsigned long offs; /* compute y-offset */
unsigned int offsi; /* result y-offset (faster then long!) */
unsigned int round; /* used to round (y * asp) / 256 */
asp = (long) (aspect * 256); /* using long is much faster! */
invrad = 0;
decision = 3 - (radius << 1);
while(invrad <= radius)
{
offs = radius * asp;
round = ((unsigned int) (offs & 0x00000080)) >> 7;
offsi = (unsigned int) ((offs >> 8) + round); /* divide by 256 (rounded) */
setpixel(x + invrad, y + offsi, selcolor(x + invrad, y + offsi));
setpixel(x + invrad, y - offsi, selcolor(x + invrad, y - offsi));
setpix